home *** CD-ROM | disk | FTP | other *** search
- Subject: v20i049: Operator interface with limited privileges
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Carel Braam <mcvax!eutrc3!rccarel>
- Posting-number: Volume 20, Issue 49
- Archive-name: opcom
-
- Opcom is a program, that enables users, belonging to a special group to
- execute a limited set of commands with another userid or groupid.
- This makes it possible to perform daily system administration tasks without
- having the full privileges of root.
-
- Carel Braam
-
- uucp: rccarel@eutrc3.UUCP | Computing Centre
- bitnet: rccarel@heithe5.BITNET | Eindhoven University of Technology
- phone: 040-472158 | Den Dolech 2, P.O. Box 513
- home: 040-810381 | 5600 MB Eindhoven, The Netherlands
-
- ---
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 1 (of 1)."
- # Contents: README bsd.make config detab.c opcom.c srctoman sysdep
- # sysv.make
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f README -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"README\"
- else
- echo shar: Extracting \"README\" \(1537 characters\)
- sed "s/^X//" >README <<'END_OF_README'
- XOpcom is a program, that enables users, belonging to a special group to
- Xexecute a limited set of commands with another userid or groupid.
- XThis makes it possible to perform daily system administration tasks without
- Xhaving the full privileges of root.
- X
- X
- XCarel Braam
- X
- Xuucp: rccarel@eutrc3.UUCP | Computing Centre
- Xbitnet: rccarel@heithe5.BITNET | Eindhoven University of Technology
- Xphone: 040-472158 | Den Dolech 2, P.O. Box 513
- Xhome: 040-810381 | 5600 MB Eindhoven, The Netherlands
- X
- X
- X INSTALLATION NOTES
- X ==================
- X
- XBefore you start off adapt the file config to your local needs.
- XAll system dependent variables are set between the comment
- X
- X# *** System dependent variables ***
- X
- Xand the comment
- X
- X# *** End system dependent variables ***
- X
- XCurrently the following variables can be set:
- X
- XOPCOMDIR The directory for the files COMMANDS and PROFILE.
- XCOMMANDS The file containing the commands, that are allowed.
- XPROFILE The file containing the profile to be executed.
- X
- XAs well the manual page opcom.8 as sysdep.h are dependent on config.
- XTo make opcom use the makefile bsd.make, if you have a bsd system, or
- Xsysv.make, if you have system V.
- XYou can create the manual page by entering make man.
- XThen as super user type make install to install opcom and make installman
- Xto install the manual page.
- XSee the makefile for the definition of the local bin directory and the local
- Xmanual directory.
- X
- X#++
- X# CREATION DATE
- X# Thu Jan 5 11:25:04 MET 1989
- X# LAST MODIFICATION
- X# Tue Jan 17 13:15:36 MET 1989
- X# VERSION/RELEASE
- X# 1.3
- X#--
- END_OF_README
- if test 1537 -ne `wc -c <README`; then
- echo shar: \"README\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f bsd.make -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"bsd.make\"
- else
- echo shar: Extracting \"bsd.make\" \(1915 characters\)
- sed "s/^X//" >bsd.make <<'END_OF_bsd.make'
- X#++
- X# NAME
- X# bsd.make
- X# SUMMARY
- X# makefile for opcom.
- X# AUTHOR(S)
- X#
- X# C.G.S.M. Braam
- X# Eindhoven University of Technology
- X# Computing Centre
- X# Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X# CREATION DATE
- X# Thu Jan 5 10:41:57 MET 1989
- X# LAST MODIFICATION
- X# Tue Jan 17 13:15:23 MET 1989
- X# VERSION/RELEASE
- X# 1.3
- X#--
- X
- X# System dependent variables
- X
- XCC = cc
- XCDEFS = -DBSD
- XCFLAGS = -O
- XLFLAGS = -h
- XBINDIR = /usr/local/bin
- XMANDIR = /usr/local/man
- X
- X# End system dependent variables
- X
- XCSOURCES = opcom.c
- XHFILES = sysdep
- XSHELLS = config
- XMAKEFILES = bsd.make sysv.make
- XOPSOURCES = $(CSOURCES) $(HFILES) $(SHELLS) $(MAKEFILES) README
- XUSOURCES = detab.c srctoman
- XSOURCES = $(OPSOURCES) $(USOURCES)
- X
- Xall: opcom
- X
- Xsysdep.h: sysdep config
- X sh config sysdep >sysdep.h
- X
- Xman: opcom.8
- X
- Xopcom.8: opcom.c config detab
- X sh srctoman -L opcom.c | sh config >opcom.8
- X
- X# Lint.
- X
- Xlint: sysdep.h
- X lint $(LFLAGS) $(CDEFS) opcom.c
- X
- X
- Xdetab: detab.c
- X $(CC) $(CFLAGS) $(CDEFS) detab.c -o detab
- X
- Xopcom: opcom.c sysdep.h
- X $(CC) $(CFLAGS) $(CDEFS) opcom.c -o opcom
- X
- X# Installation and update.
- X
- Xinstall: opcom
- X cp opcom $(BINDIR)
- X cd $(BINDIR); chown root opcom; chmod u+s opcom
- X
- Xinstallman: man
- X cp opcom.8 $(MANDIR)/man8
- X rm -f $(MANDIR)/cat8/opcom.8
- X
- Xarchive: $(OPSOURCES)
- X archive $(OPSOURCES)
- X
- Xrelease: $(OPSOURCES)
- X modsource +1 $(CSOURCES)
- X modsource +2 $(CSOURCES)
- X modsource +1 -c $(HFILES)
- X modsource +2 -c $(HFILES)
- X modsource +1 -mk $(MAKEFILES) README
- X modsource +2 -mk $(MAKEFILES) README
- X modsource +1 - $(SHELLS)
- X modsource +2 - $(SHELLS)
- X archive $(OPSOURCES)
- X
- Xversion: $(OPSOURCES)
- X modsource -1 $(CSOURCES)
- X modsource -1 -c $(HFILES)
- X modsource -1 -mk $(MAKEFILES) README
- X modsource -1 - $(SHELLS)
- X archive $(OPSOURCES)
- X
- Xshar: $(SOURCES)
- X rm -f Part?? Part??.Z
- X makekit $(SUBDIRS) $(SOURCES) $(DIRENT)
- X
- Xclean:
- X -rm -f *.BAK *.o opcom detab opcom.8 tmp.* sysdep.h \
- X nohup.out core Part?? Part??.Z
- END_OF_bsd.make
- if test 1915 -ne `wc -c <bsd.make`; then
- echo shar: \"bsd.make\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f config -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"config\"
- else
- echo shar: Extracting \"config\" \(789 characters\)
- sed "s/^X//" >config <<'END_OF_config'
- X: use /bin/sh
- X
- X# opcom configuration script.
- X#
- X# In the first part of this script the directories and the administration
- X# for opcom are defined.
- X# Refer to all of these only by the environment variables defined here.
- X
- X#++
- X# AUTHOR(S)
- X#
- X# C.G.S.M. Braam
- X# Eindhoven University of Technology
- X# Computing Centre
- X# Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X# CREATION DATE
- X# Thu Jan 5 11:09:45 MET 1989
- X# LAST MODIFICATION
- X# Tue Jan 17 13:15:48 MET 1989
- X# VERSION/RELEASE
- X# 1.3
- X#--
- X
- X# *** System dependent variables ***
- X
- XOPCOMDIR="/usr/local/lib/opcom"
- XCOMMANDS="$OPCOMDIR/commands" # command file
- XPROFILE="$OPCOMDIR/profile" # profile
- X
- X# *** End system dependent variables ***
- X
- Xsed 's%XCOMMANDS%'"$COMMANDS"'%g
- X s%XPROFILE%'"$PROFILE"'%g' $*
- END_OF_config
- if test 789 -ne `wc -c <config`; then
- echo shar: \"config\" unpacked with wrong size!
- fi
- chmod +x config
- # end of overwriting check
- fi
- if test -f detab.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"detab.c\"
- else
- echo shar: Extracting \"detab.c\" \(1053 characters\)
- sed "s/^X//" >detab.c <<'END_OF_detab.c'
- X/*++
- X/* NAME
- X/* detab 1
- X/* SUMMARY
- X/* expand tabs to blanks
- X/* PROJECT
- X/* documentation
- X/* SYNOPSIS
- X/* detab
- X/* DESCRIPTION
- X/* Detab is a filter that expands tab stops in its standard input
- X/* to blanks. A tab stop distance of eight blanks is assumed.
- X/* BUGS
- X/* This program does not handle backspaces.
- X/* AUTHOR(S)
- X/* Wietse Venema
- X/* Eindhoven University of Technology
- X/* Department of Mathematics and Computer Science
- X/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X/* CREATION DATE
- X/* Sep 14 1985
- X/* LAST MODIFICATION
- X/* Mon May 4 20:32:48 GMT+1:00 1987
- X/* VERSION/RELEASE
- X/* 1.3
- X/*--*/
- X
- X#include <stdio.h>
- X
- X#define BLANK ' '
- X
- Xmain()
- X{
- X register int c; /* character buffer */
- X register int ccount = 0; /* nr of characters printed on current line */
- X
- X while ((c = getchar()) != EOF) {
- X switch (c) {
- X
- X case '\r':
- X case '\n': putchar(c);
- X ccount = 0;
- X break;
- X
- X case '\t': do { putchar(BLANK); } while (++ccount & 7);
- X break;
- X
- X default: putchar(c);
- X ccount++;
- X break;
- X }
- X }
- X exit(0);
- X}
- END_OF_detab.c
- if test 1053 -ne `wc -c <detab.c`; then
- echo shar: \"detab.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f opcom.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"opcom.c\"
- else
- echo shar: Extracting \"opcom.c\" \(9468 characters\)
- sed "s/^X//" >opcom.c <<'END_OF_opcom.c'
- X/*++
- X/* NAME
- X/* opcom 8
- X/* SUMMARY
- X/* execute an operator command.
- X/* SYNOPSIS
- X/* .fi
- X/* .B opcom
- X/* command [ arguments ]
- X/* DESCRIPTION
- X/* .I Opcom
- X/* enables users belonging to a special group (as defined in /etc/group)
- X/* to execute a limited set of commands with another userid (e.g. root)
- X/* or groupid. The file
- X/* .I XCOMMANDS
- X/* describes which commands are allowed for which groups and which
- X/* userid (groupid) must be used.
- X/* .br
- X/* .I Command
- X/* is a valid operator command, if it matches an entry in
- X/* .I XCOMMANDS.
- X/* Those entries have the following form:
- X/*
- X/* path-name : operator-group : [ new-userid ] [ : [ new-groupid ]]
- X/*
- X/* .I Command
- X/* matches an entry, if it is the basename of
- X/* .I path-name
- X/* and if the user executing
- X/* .I opcom
- X/* is a member of the group
- X/* .I operator-group
- X/* (as defined in /etc/group).
- X/* If
- X/* .I command
- X/* matches more than one entry, the first matching entry is selected.
- X/* This allows multiple levels of privilege.
- X/* .br
- X/* If no match is found,
- X/* .I opcom
- X/* aborts with the message "access denied.".
- X/*
- X/* .I Command
- X/* is executed with the given
- X/* .I arguments.
- X/* The environment is the current environment with the following
- X/* exceptions:
- X/* .br
- X/* If
- X/* .I user-id (group-id)
- X/* is not empty, the effective and real userid (groupid) are set to
- X/* .I user-id (group-id).
- X/* .br
- X/* If
- X/* .I user-id (group-id)
- X/* is empty, the effective and real userid (groupid)
- X/* are set to the real userid (groupid).
- X/*
- X/* The following environment variables are set:
- X/* .IP \- 2.4
- X/* COMMAND to
- X/* .I command.
- X/* .IP \-
- X/* GROUP to
- X/* .I operator-group.
- X/* .IP \-
- X/* IFS to blank, tab and new line.
- X/* .IP \-
- X/* ORGUSER to the login name of the real userid of the invoker of
- X/* .I opcom.
- X/* .IP \-
- X/* PATH to /
- X/* .IP \-
- X/* USER and LOGNAME to the login name of the real userid executing
- X/* .I command.
- X/* .RE
- X/*
- X/* If the script
- X/* .I XPROFILE
- X/* exists, this script will be executed
- X/* within the shell, that executes
- X/* .I command.
- X/* So changes to the environment (e.g. PATH) can be put there.
- X/* FILES
- X/* XCOMMANDS
- X/* XPROFILE
- X/* /etc/group
- X/* CAVEAT
- X/* Beware of Trojan horses: don't allow commands with shell escapes.
- X/* BUGS
- X/* The syntax of entries in
- X/* .I XCOMMANDS
- X/* is not checked rigorously.
- X/* DIAGNOSTICS
- X/* In case of error
- X/* .I opcom
- X/* prints an error message on standard error and terminates
- X/* with nonzero status.
- X/* AUTHOR(S)
- X/*
- X/* C.G.S.M. Braam
- X/* Eindhoven University of Technology
- X/* Computing Centre
- X/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X/* BUG REPORTS TO
- X/* rccarel@eutrc3.UUCP
- X/* CREATION DATE
- X/* Wed Jan 4 14:12:59 MET 1989
- X/* LAST MODIFICATION
- X/* Tue Jan 17 13:15:08 MET 1989
- X/* VERSION/RELEASE
- X/* 1.3
- X/*--*/
- X
- X#include <stdio.h>
- X#include "sysdep.h"
- X#include <grp.h>
- X#include <pwd.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <varargs.h>
- X#include <ctype.h>
- X
- Xextern void exit ();
- Xextern void perror ();
- X
- Xextern int errno;
- Xextern char *sys_errlist [];
- Xextern int sys_nerr;
- X
- Xextern int geteuid ();
- Xextern int getgid ();
- Xextern int setuid ();
- Xextern struct group *getgrnam ();
- Xextern struct passwd *getpwnam ();
- Xextern struct passwd *getpwuid ();
- Xextern char *malloc ();
- Xextern int putenv ();
- Xextern int system ();
- X
- X#define WARN 0
- X#define ABORT 1
- X
- Xstruct command {
- X char *name;
- X char path [1024];
- X char group [32];
- X char new_group [32];
- X char new_user [32];
- X};
- X
- Xvoid PERROR ();
- Xint check_group ();
- Xvoid error ();
- Xvoid exec_cmnd ();
- Xstruct command *get_command ();
- Xchar *nextitem ();
- Xvoid usage_error ();
- Xvoid set_env ();
- Xvoid set_ids ();
- X
- Xchar orguser [32];
- Xchar *progname; /* used for diagnostics */
- X
- Xmain (argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X int fd;
- X struct command *command;
- X
- X /* close all file descriptors > 2 */
- X for (fd = 3; fd <= _NFILE; fd++)
- X (void) close (fd);
- X if (progname = strrchr (*argv, '/'))
- X progname++;
- X else
- X progname = *argv;
- X argv++; argc--;
- X
- X if (argc == 0)
- X usage_error ();
- X
- X command = get_command (*argv);
- X set_ids (command->new_user, command->new_group);
- X exec_cmnd (command, argc-1, argv+1);
- X return (0); /* makes lint happy */
- X}
- X
- Xstruct command *get_command (name)
- Xchar *name;
- X{
- X static char cmndbuf [BUFSIZ];
- X static struct command command;
- X int found = 0;
- X char ch,
- X *cmnd,
- X *pc,
- X *ptail,
- X *pt;
- X FILE *file;
- X
- X if ((file = fopen (COMMANDS, "r")) == NULL)
- X error (ABORT, "cannot open %s for reading.", COMMANDS);
- X command.name = name;
- X while (fgets (cmndbuf, BUFSIZ, file) != NULL) {
- X for (cmnd = cmndbuf; isspace (*cmnd); cmnd++);
- X pt = command.path;
- X ptail = cmnd;
- X while (! (isspace (ch = *ptail) || (ch == ':') || (ch == 0))) {
- X *pt++ = ch;
- X ptail++;
- X }
- X *pt = 0;
- X while (isspace (*ptail))
- X ptail++;
- X if (*ptail != ':') /* invalid entry */
- X continue;
- X pt = command.path;
- X if ((pc = strrchr (pt, '/')) == NULL)
- X pc = pt;
- X else
- X pc++;
- X if (strcmp (name, pc) == 0) {
- X ptail = nextitem (ptail+1, command.group);
- X if ((found = check_group (command.group)))
- X break;
- X }
- X }
- X if (! found)
- X error (ABORT, "access denied.");
- X (void) fclose (file);
- X ptail = nextitem (ptail, command.new_user);
- X ptail = nextitem (ptail, command.new_group);
- X return (&command);
- X}
- X
- Xchar *nextitem (pstart, target)
- Xchar *pstart,
- X *target;
- X{
- X char ch,
- X *ps = pstart,
- X *pt = target;
- X
- X while (isspace (*ps)) ps++;
- X if (*ps == 0) {
- X *pt = 0;
- X return (ps);
- X }
- X for (ch = *ps; (ch != ':') & (ch != 0); ch = *++ps)
- X *pt++ = ch;
- X *pt-- = 0;
- X for (ch = *pt; isspace (ch); ch = *pt--)
- X *pt = 0;
- X if (*ps == 0)
- X return (ps);
- X else
- X return (ps+1);
- X}
- X
- Xint check_group (groupname)
- Xchar *groupname;
- X{
- X int found = 0;
- X char **gr_list;
- X struct group *group;
- X struct passwd *passwd;
- X
- X if ((passwd = getpwuid (getuid ())) == NULL)
- X error (ABORT, "cannot find passwd entry for userid %d.", getuid ());
- X (void) strcpy (orguser, passwd->pw_name);
- X if ((group = getgrnam (groupname)) != NULL)
- X for (gr_list = group->gr_mem; *gr_list != NULL; gr_list++) {
- X if ((found = (strcmp (orguser, *gr_list) == 0)))
- X break;
- X }
- X return (found);
- X}
- X
- Xvoid set_ids (new_user, new_group)
- Xchar *new_user,
- X *new_group;
- X{
- X struct group *group;
- X struct passwd *passwd;
- X
- X if (*new_group != 0) {
- X /* not empty, must be set before uid is set */
- X if ((group = getgrnam (new_group)) == NULL)
- X error (ABORT, "cannot find group entry for groupid %s.", new_group);
- X if (setgid (group->gr_gid) < 0)
- X PERROR (ABORT);
- X }
- X if (*new_user != 0) { /* not empty */
- X if ((passwd = getpwnam (new_user)) == NULL)
- X error (ABORT, "cannot find passwd entry for userid %s.", new_user);
- X if (setuid (passwd->pw_uid) < 0)
- X PERROR (ABORT);
- X } else if (setuid (getuid ()) < 0)
- X PERROR (ABORT);
- X}
- X
- Xvoid exec_cmnd (command, argc, argv)
- Xstruct command *command;
- Xint argc;
- Xchar **argv;
- X{
- X unsigned cmnd_size = 0;
- X int i,
- X rslt;
- X struct stat prstat;
- X char
- X *cmnd,
- X *pa,
- X *pc;
- X
- X set_env (command->name, command->group, command->new_user);
- X cmnd_size = strlen (command->path)+32;
- X for (i = 0; i < argc; i++)
- X cmnd_size += strlen (argv [i])+1;
- X pc = cmnd = malloc (cmnd_size+strlen (PROFILE));
- X if ((stat (PROFILE, &prstat) == 0) && (prstat.st_mode & 0400)) {
- X /* We must execute the profile */
- X (void) sprintf (pc, ". %s;", PROFILE);
- X pc += strlen (pc);
- X }
- X pa = command->path;
- X while (*pa != 0)
- X *pc++ = *pa++;
- X *pc++ = ' ';
- X while (argc-- > 0) {
- X pa = *argv++;
- X while (*pa != 0)
- X *pc++ = *pa++;
- X *pc++ = ' ';
- X }
- X *pc = 0; /* close string */
- X
- X if ((rslt = system (cmnd)) < 0)
- X PERROR (ABORT);
- X exit (rslt);
- X}
- X
- Xvoid set_env (name, group, new_user)
- Xchar *name,
- X *group,
- X *new_user;
- X{
- X#define PUTENV(e) { if (putenv (e) < 0) PERROR (ABORT); }
- X static char envbuf [512];
- X char *penv = envbuf;
- X
- X PUTENV ("IFS= \t\n");
- X PUTENV ("PATH=/");
- X (void) sprintf (penv, "ORGUSER=%s", orguser);
- X PUTENV (penv);
- X penv += strlen (penv)+1;
- X (void) sprintf (penv, "COMMAND=%s", name);
- X PUTENV (penv);
- X penv += strlen (penv)+1;
- X (void) sprintf (penv, "GROUP=%s", group);
- X PUTENV (penv);
- X penv += strlen (penv)+1;
- X if (*new_user == 0) {
- X (void) sprintf (penv, "USER=%s", orguser);
- X PUTENV (penv);
- X penv += strlen (penv)+1;
- X (void) sprintf (penv, "LOGNAME=%s", orguser);
- X PUTENV (penv);
- X } else {
- X (void) sprintf (penv, "USER=%s", new_user);
- X PUTENV (penv);
- X penv += strlen (penv)+1;
- X (void) sprintf (penv, "LOGNAME=%s", new_user);
- X PUTENV (penv);
- X }
- X}
- X
- Xvoid PERROR (why)
- Xint why;
- X{
- X perror (progname);
- X if (why == ABORT)
- X exit (1);
- X}
- X
- Xvoid usage_error ()
- X{
- X error (ABORT, "usage: %s command [ arguments ]", progname);
- X}
- X
- X/* error - barf and quit */
- X
- X/* VARARGS1 */
- X
- Xvoid error (why, fmt, va_alist)
- Xint why;
- Xregister char *fmt;
- Xva_dcl
- X{
- X va_list s;
- X
- X va_start(s);
- X
- X (void) fprintf (stderr, "%s: ", progname);
- X for (/* void */; *fmt; fmt++) {
- X if (*fmt != '%') {
- X (void) putc(*fmt,stderr);
- X } else if (*++fmt == 's') {
- X (void) fputs(va_arg(s,char *),stderr);
- X } else if (*fmt == 'c') {
- X (void) putc(va_arg(s,int),stderr);
- X } else if (*fmt == 'u') {
- X (void) fprintf(stderr,"%u",va_arg(s,unsigned));
- X } else if (*fmt == 'd') {
- X (void) fprintf(stderr,"%d",va_arg(s,int));
- X }
- X }
- X va_end(s);
- X (void) fprintf (stderr, "\n");
- X if (why != WARN)
- X exit (why);
- X (void) fflush (stderr);
- X}
- END_OF_opcom.c
- if test 9468 -ne `wc -c <opcom.c`; then
- echo shar: \"opcom.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f srctoman -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"srctoman\"
- else
- echo shar: Extracting \"srctoman\" \(4670 characters\)
- sed "s/^X//" >srctoman <<'END_OF_srctoman'
- X: srctoman - see comment below
- X
- X: process arguments
- X
- XLOCAL=
- XHOST=
- Xwhile :
- Xdo
- X case $1 in
- X -L) HOST=`uuname -l | tr "[a-z]" "[A-Z]"`
- X LOCAL=LOCAL;;
- X [0-9]) SECT=$1;;
- X -) LANG=$1; B='[#:]';;
- X -awk) LANG=$1; B='#';;
- X -c) LANG=$1; B='\/\*';;
- X -f) LANG=$1; B='[Cc]';;
- X -mk) LANG=$1; B='#';;
- X -n|-t) LANG=$1; B='\\"';;
- X -p) LANG=$1; B='{';;
- X -r) LANG=$1; B='#';;
- X -C) LANG=$1; B=$2; shift;;
- X -*) ERROR="unknown option: $1"; break;;
- X "") ERROR="missing file argument"; break;;
- X *) break;;
- X esac
- X shift
- Xdone
- X
- X: check error status
- X
- Xcase $ERROR in
- X"") ;;
- X *) echo "$0: $ERROR" 1>&2
- X echo "usage: $0 [-|-awk|-c|-f|-mk|-n|-p|-t|-r] [section] file(s)" 1>&2; exit 1;;
- Xesac
- X
- X: set up for file suffix processing
- X
- Xcase $LANG in
- X"") sh='[:#]'; r='#'; rh=$r; awk='#'; mk='#';
- X c='\/\*'; h=$c; y=$c; l=$c;
- X f='[Cc]'; fh=$f; p='{'; ph=$p;
- X ms='\\"'; nr=$ms; mn=$ms; man=$ms;
- Xesac
- X
- X: extract comments
- X
- Xfor i in $*
- Xdo
- X case $LANG in
- X "") eval B\="\$`expr $i : '^.*\.\([^.]*\)$'`"
- X test "$B" || { echo "$0: unknown suffix: $i; assuming c" 1>&2; B=$c; }
- X esac
- X sed '
- X /^'"$B"'++/,/^'"$B"'--/!d
- X /^'"$B"'++/d
- X /^'"$B"'--/d
- X s/[ ]*$//
- X /^'"$B"' \([A-Z]\)/{
- X s//\1/
- X /^NAME/{
- X N
- X s/^.*\n'"$B"'[ ]*//
- X h
- X y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
- X s/,.*\([ ][0-9][ ]*\)$/ \1/
- X s/^.*$/.TH & '"$SECT $LOCAL $HOST"'\
- X.ad\
- X.fi\
- X.SH NAME/
- X p
- X g
- X s/[ ][0-9][ ]*$//
- X a\
- X\\-
- X p
- X d
- X }
- X /^SUMMARY/d
- X /^DESCRIPTION/s//.SH &\
- X.ad\
- X.fi/
- X /^BUGS/s//.SH &\
- X.ad\
- X.fi/
- X /^DIAGNOSTICS/s//.SH &\
- X.ad\
- X.fi/
- X /^[A-Z][A-Z][A-Z][^a-z]*$/s//.SH &\
- X.na\
- X.nf/
- X p
- X d
- X }
- X s/^'"$B"'[ ]*//
- X s/^[ ]*$//
- X' $i
- Xdone | ./detab
- X
- Xexit
- X
- X:++
- X: NAME
- X: srctoman 1
- X: SUMMARY
- X: extract manual page from source file comment
- X: PACKAGE
- X: source file maintentance tools
- X: SYNOPSIS
- X: srctoman [-|-awk|-c|-f|-mk|-m|-n|-p|-t|-r] [section] file(s)
- X: DESCRIPTION
- X: Sourcetoman converts comments in various programming languages to
- X: UNIX-style manual pages.
- X: The command processes comments in the style of newsource(1);
- X: its standard output is suitable for formatting with nroff(1) or
- X: troff(1) using the "-man" macro package.
- X: Typically, srctoman is integrated with make(1) scripts.
- X: If the option -L is given the text <hostname> (LOCAL) will be in
- X: the heading.
- X:
- X: Source files are processed in the indicated order; if no
- X: files argument the command produces no output.
- X:
- X: The source file language can be specified through a command-line
- X: option, or can be implied by the filename suffix.
- X: The expected start-of-comment symbol is shown in the last column.
- X:
- X: .nf
- X option language comment
- X
- X - shell [:#]
- X -awk awk #
- X -c c /*
- X -f fortran [Cc]
- X -mk make #
- X -n nroff \\"
- X -p pascal {
- X -t troff \\"
- X -r ratfor #
- X -C any language next argument
- X: .fi
- X:
- X: .nf
- X suffix language comment
- X
- X .awk awk #
- X .c c /*
- X .f fortran [Cc]
- X .fh fortran [Cc]
- X .h c /*
- X .l lex /*
- X .man nroff,troff \\"
- X .mk make #
- X .me nroff,troff \\"
- X .ms nroff,troff \\"
- X .nr nroff,troff \\"
- X .p pascal {
- X .ph pascal {
- X .r ratfor #
- X .rh ratfor #
- X .sh shell [:#]
- X .y yacc /*
- X: .fi
- X:
- X: The required format of comments is discussed below, where SOC
- X: stands for the start-of-comment symbol of the language being used.
- X:
- X: 1) Start of manual: SOC, followed by `++'.
- X:
- X: 2) Section heading: SOC, blank, section name in upper case.
- X:
- X: 3) New paragraph: empty line or line with SOC only.
- X:
- X: 4) All other text: SOC and subsequent blanks or tabs are removed.
- X: Lines that do not start with SOC are left unchanged (useful for
- X: inclusion of program text).
- X:
- X: 5) End of manual: SOC, followed by `--'.
- X: An end-of-comment may follow if the source file language requires this.
- X:
- X: The following manual sections receive a special treatment:
- X: NAME and SUMMARY should appear at the beginning and in
- X: this order; DESCRIPTION, DIAGNOSTICS and BUGS will be
- X: right-margin adjusted.
- X: Other sections may be added freely without confusing srctoman.
- X: COMMANDS
- X: sh(1), sed(1), detab(1)
- X: SEE ALSO
- X: newsource(1), modsource(1), xman(1)
- X: The earlier commands new(1), mod(1), mkman(1) and dssman(1)
- X: by Ruud Zwart and Ben Noordzij (Erasmus University, Rotterdam)
- X: DIAGNOSTICS
- X: The program complaints if an unknown language is specified
- X: of if the language cannot be deduced from the file suffix.
- X: AUTHOR(S)
- X: W.Z. Venema
- X: Eindhoven University of Technology
- X: Department of Mathematics and Computer Science
- X: Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X: CREATION DATE
- X: Fri Jan 17 22:59:27 MET 1986
- X: LAST MODIFICATION
- X: Tue Mar 22 07:24:47 PST 1988
- X: VERSION/RELEASE
- X: 1.20
- X:--
- X
- X
- END_OF_srctoman
- if test 4670 -ne `wc -c <srctoman`; then
- echo shar: \"srctoman\" unpacked with wrong size!
- fi
- chmod +x srctoman
- # end of overwriting check
- fi
- if test -f sysdep -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"sysdep\"
- else
- echo shar: Extracting \"sysdep\" \(272 characters\)
- sed "s/^X//" >sysdep <<'END_OF_sysdep'
- X#ifndef _NFILE
- X#include <sys/param.h>
- X#define _NFILE NOFILE
- X#endif
- X
- X#ifdef SYSV
- X#define SIII
- X#include <string.h>
- X#else
- X#include <strings.h>
- X#define strchr index
- X#define strrchr rindex
- Xextern char *ctime ();
- X#endif
- X
- X#define COMMANDS "XCOMMANDS"
- X#define PROFILE "XPROFILE"
- END_OF_sysdep
- if test 272 -ne `wc -c <sysdep`; then
- echo shar: \"sysdep\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f sysv.make -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"sysv.make\"
- else
- echo shar: Extracting \"sysv.make\" \(1921 characters\)
- sed "s/^X//" >sysv.make <<'END_OF_sysv.make'
- X#++
- X# NAME
- X# sysv.make
- X# SUMMARY
- X# makefile for opcom.
- X# AUTHOR(S)
- X#
- X# C.G.S.M. Braam
- X# Eindhoven University of Technology
- X# Computing Centre
- X# Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X# CREATION DATE
- X# Thu Jan 5 10:41:57 MET 1989
- X# LAST MODIFICATION
- X# Tue Jan 17 13:15:28 MET 1989
- X# VERSION/RELEASE
- X# 1.3
- X#--
- X
- X# System dependent variables
- X
- XCC = cc
- XCDEFS = -DSYSV
- XCFLAGS = -O
- XLFLAGS = -h -Ml
- XBINDIR = /usr/local/bin
- XMANDIR = /usr/local/man
- X
- X# End system dependent variables
- X
- XCSOURCES = opcom.c
- XHFILES = sysdep
- XSHELLS = config
- XMAKEFILES = bsd.make sysv.make
- XOPSOURCES = $(CSOURCES) $(HFILES) $(SHELLS) $(MAKEFILES) README
- XUSOURCES = detab.c srctoman
- XSOURCES = $(OPSOURCES) $(USOURCES)
- X
- Xall: opcom
- X
- Xsysdep.h: sysdep config
- X sh config sysdep >sysdep.h
- X
- Xman: opcom.8
- X
- Xopcom.8: opcom.c config detab
- X sh srctoman -L opcom.c | sh config >opcom.8
- X
- X# Lint.
- X
- Xlint: sysdep.h
- X lint $(LFLAGS) $(CDEFS) opcom.c
- X
- X
- Xdetab: detab.c
- X $(CC) $(CFLAGS) $(CDEFS) detab.c -o detab
- X
- Xopcom: opcom.c sysdep.h
- X $(CC) $(CFLAGS) $(CDEFS) opcom.c -o opcom
- X
- X# Installation and update.
- X
- Xinstall: opcom
- X cp opcom $(BINDIR)
- X cd $(BINDIR); chown root opcom; chmod u+s opcom
- X
- Xinstallman: man
- X cp opcom.8 $(MANDIR)/man8
- X rm -f $(MANDIR)/cat8/opcom.8
- X
- Xarchive: $(OPSOURCES)
- X archive $(OPSOURCES)
- X
- Xrelease: $(OPSOURCES)
- X modsource +1 $(CSOURCES)
- X modsource +2 $(CSOURCES)
- X modsource +1 -c $(HFILES)
- X modsource +2 -c $(HFILES)
- X modsource +1 -mk $(MAKEFILES) README
- X modsource +2 -mk $(MAKEFILES) README
- X modsource +1 - $(SHELLS)
- X modsource +2 - $(SHELLS)
- X archive $(OPSOURCES)
- X
- Xversion: $(OPSOURCES)
- X modsource -1 $(CSOURCES)
- X modsource -1 -c $(HFILES)
- X modsource -1 -mk $(MAKEFILES) README
- X modsource -1 - $(SHELLS)
- X archive $(OPSOURCES)
- X
- Xshar: $(SOURCES)
- X rm -f Part?? Part??.Z
- X makekit $(SUBDIRS) $(SOURCES) $(DIRENT)
- X
- Xclean:
- X -rm -f *.BAK *.o opcom detab opcom.8 tmp.* sysdep.h \
- X nohup.out core Part?? Part??.Z
- END_OF_sysv.make
- if test 1921 -ne `wc -c <sysv.make`; then
- echo shar: \"sysv.make\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of archive 1 \(of 1\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 1 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-